/* QtLua -- Lua bindings for Qt
   Copyright (C) 2011, Jarek Pelczar

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 3 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General
   Public License along with this library; if not, write to the
   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301 USA

*/

#include "qluascriptcontextinfo_p.h"
#include "qluascriptcontext_p.h"

QLuaScriptContextInfo::QLuaScriptContextInfo(QLuaScriptContext * context)
{
    d = NULL;
    if(!context)
        return;
    QLuaScriptContextPrivate * priv = QLuaScriptContextPrivate::priv(context);
    d = priv->m_contextInfo;
}

QLuaScriptContextInfo::~QLuaScriptContextInfo()
{
}

QLuaScriptContextInfo::QLuaScriptContextInfo(const QLuaScriptContextInfo& other)
{
    d = other.d;
}

QLuaScriptContextInfo& QLuaScriptContextInfo::operator = (const QLuaScriptContextInfo& other)
{
    if(this != &other)
        d = other.d;
    return *this;
}

QString QLuaScriptContextInfo::fileName() const
{
    return d ? d->m_scriptName : QString();
}

QString QLuaScriptContextInfo::functionName() const
{
    return d ? d->m_functionName : QString();
}

int QLuaScriptContextInfo::functionEndLineNumber() const
{
    return d? d->m_endLine : -1;
}

int QLuaScriptContextInfo::functionStartLineNumber() const
{
    return d ? d->m_startLine : -1;
}

int QLuaScriptContextInfo::lineNumber() const
{
    return d ? d->m_currentLine : -1;
}

qint64 QLuaScriptContextInfo::scriptId() const
{
    return d ? d->m_scriptId : -1;
}

QLuaScriptContextInfo::FunctionType QLuaScriptContextInfo::functionType() const
{
    return d ? d->m_type : QLuaScriptContextInfo::UnknownFunction;
}

int QLuaScriptContextInfo::countUpValues() const
{
    return d ? d->m_upValueCount : 0;
}

QHash<QByteArray, int> QLuaScriptContextInfo::localVariables() const
{
    QHash<QByteArray, int> list;
    if(!d) {
#ifdef QT_DEBUG
        qDebug() << "QLuaScriptContextInfo: NULL context";
#endif
        return list;
    }
    lua_Debug ar;
    lua_State * L = d->m_engine->L;
    lua_getstack(L, d->m_contextPrivate->m_activationRecordId, &ar);
    const char * ptr;
    int n = 0;
    while((ptr = lua_getlocal(L, &ar, n++)) != NULL) {
        lua_pop(L, 1);
        list.insert(ptr, n - 1);
    }
#ifdef QT_DEBUG
        qDebug() << "QLuaScriptContextInfo: variables are" << list;
#endif
    return list;
}

QPair<QByteArray, QLuaScriptValue> QLuaScriptContextInfo::localVariable(int index) const
{
    QPair<QByteArray, QLuaScriptValue> item;
    if(!d)
        return item;
    lua_Debug ar;
    lua_State * L = d->m_engine->L;
    lua_getstack(L, d->m_contextPrivate->m_activationRecordId, &ar);
    const char * ptr = lua_getlocal(L, &ar, index);
    if(!ptr) return QPair<QByteArray, QLuaScriptValue>();
    QPair<QByteArray, QLuaScriptValue> retv(ptr, QLuaScriptValue::newFromStack(d->m_engine->q_ptr, -1));
    lua_pop(L, 1);
    return retv;
}

void QLuaScriptContextInfo::setLocalVariable(int index, const QLuaScriptValue& value)
{
    if(!d)
        return;
    lua_Debug ar;
    lua_State * L = d->m_engine->L;
    lua_getstack(L, d->m_contextPrivate->m_activationRecordId, &ar);
    value.pushToStack(d->m_engine->q_ptr);
    lua_setlocal(L, &ar, index);
}

int QLuaScriptContextInfo::activationContext() const
{
    if(!d)
        return -1;
    return d->m_contextPrivate->m_activationRecordId;
}

QLuaScriptEngine * QLuaScriptContextInfo::engine() const
{
    if(!d)
        return NULL;
    return d->m_contextPrivate->m_engine;
}
